package com.ruoyi.door.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.exception.ExcelAnalysisStopException;
import com.alibaba.excel.read.listener.ReadListener;
import com.easy.query.api.proxy.client.EasyEntityQuery;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.SysDeptUtil;
import com.ruoyi.door.controller.admin.adsl.vo.DoorAdslChangeGuidReqVO;
import com.ruoyi.door.controller.admin.adsl.vo.DoorAdslImportVO;
import com.ruoyi.door.controller.admin.adsl.vo.DoorAdslImportRespVO;
import com.ruoyi.door.domain.DoorAdsl;
import com.ruoyi.door.domain.DoorGuidLog;
import com.ruoyi.door.domain.DoorHouse;
import com.ruoyi.door.excel.UserDataListener;
import com.ruoyi.system.mapper.SysDeptMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

@Service
public class DoorAdslService {
    @Autowired
    private EasyEntityQuery easyEntityQuery;
    @Autowired
    private SysDeptMapper sysDeptMapper;
    @Autowired
    private RedisCache redisCache;
    private final String IMPORT_KRY = "adslimport";

    @Transactional
    public Map<String, Object> importData(MultipartFile file, String uuid) throws IOException {
        List<DoorAdslImportVO> vos = new ArrayList<>();
        System.out.println(DateUtil.now()+"读取Excel开始");

        EasyExcel.read(file.getInputStream(), DoorAdslImportVO.class, new ReadListener<DoorAdslImportVO>() {

            @Override
            public void invoke(DoorAdslImportVO vo, AnalysisContext analysisContext) {

                vos.add(vo);
            }

            @Override
            public void doAfterAllAnalysed(AnalysisContext analysisContext) {

            }
        })
                .ignoreEmptyRow(true)            // 忽略空行，提升性能
                .headRowNumber(1)                // 明确指定表头行数
                .autoCloseStream(true)           // 自动关闭流
                .sheet().doRead();
        System.out.println(DateUtil.now()+"读取Excel结束");

        List<SysDept> deptList = sysDeptMapper.selectDeptList(new SysDept());
        System.out.println(DateUtil.now()+"读取房产表开始");
        List<DoorHouse> houseList = easyEntityQuery.queryable(DoorHouse.class).toList();
        System.out.println(DateUtil.now()+"读取房产表结束");


        System.out.println(DateUtil.now()+"房产组装map开始");

        // 创建房产唯一标识到房产对象的映射，提高查找效率
        Map<String, DoorHouse> houseKeyMap = new HashMap<>();
        for (DoorHouse house : houseList) {
            String key = house.getProvince() + "-" + 
                        house.getCity() + "-" + 
                        house.getDistrict() + "-" + 
                        house.getStreet() + "-" + 
                        house.getVillage() + "-" + 
                        house.getAddress();
            houseKeyMap.put(key, house);
        }
        System.out.println(DateUtil.now()+"房产组装map结束");

        System.out.println(DateUtil.now()+"读取ADSL表开始");
        List<DoorAdsl> adslList = easyEntityQuery.queryable(DoorAdsl.class).toList();
        System.out.println(DateUtil.now()+"读取ADSL表结束");

        Map<String, DoorAdsl> adslKeyMap = new HashMap<>();
        for (DoorAdsl adsl : adslList) {
            if (adsl.getHouseId() == null) {
                continue;
            }
            String standardAddress = StrUtil.trimToEmpty(adsl.getStandardAddress());
            if (StringUtils.isEmpty(standardAddress)) {
                continue;
            }
            String key = adsl.getHouseId() + "-" + standardAddress;
            adslKeyMap.put(key, adsl);
        }

        int insertCount = 0;
        int updateCount = 0;
        int failCount = 0;
        List<DoorAdslImportRespVO> failureList = new ArrayList<>();


        List<DoorAdsl>insertList = new ArrayList<>();
        List<DoorAdsl>updateList = new ArrayList<>();

        for (int i = 0; i < vos.size(); i++) {
            DoorAdslImportVO adslImportVO = vos.get(i);
            try {
                // 处理ADSL记录
                // 验证部门信息并查找对应的房产
                SysDept root = new SysDept();
                root.setDeptId(0L);
                SysDept country = SysDeptUtil.findDeptById(adslImportVO.getCountryName(), 1, root, deptList);
                if (country == null) {
                    throw new Exception("公司不存在或层级关系错误");
                }
                SysDept province = SysDeptUtil.findDeptById(adslImportVO.getProvinceName(), 2, country, deptList);
                SysDept city = SysDeptUtil.findDeptById(adslImportVO.getCityName(), 3, province, deptList);
                SysDept district = SysDeptUtil.findDeptById(adslImportVO.getDistrictName(), 4, city, deptList);
                SysDept street = SysDeptUtil.findDeptById(adslImportVO.getStreetName(), 5, district, deptList);
                SysDept village = SysDeptUtil.findDeptById(adslImportVO.getVillageName(), 6, street, deptList);

                if (province == null) {
                    throw new Exception("省级部门信息不完整或层级关系错误");

                }
                if (city == null) {
                    throw new Exception("市级部门信息不完整或层级关系错误");

                }
                if (district == null ) {
                    throw new Exception("镇级部门信息不完整或层级关系错误");

                }if (street == null ) {
                    throw new Exception("街道部门信息不完整或层级关系错误");

                }if ( village == null) {
                    throw new Exception("村级部门信息不完整或层级关系错误");

                }
                String address = adslImportVO.getAddress();
                String houseKey = province.getDeptId() + "-" + 
                                 city.getDeptId() + "-" + 
                                 district.getDeptId() + "-" + 
                                 street.getDeptId() + "-" +
                                 village.getDeptId() + "-" + 
                                 address;
                DoorHouse doorHouse = houseKeyMap.get(houseKey);

                if (doorHouse == null) {
                    throw new Exception("找不到对应的房产信息");

                }
                DoorAdsl doorAdsl = new DoorAdsl();
                BeanUtil.copyProperties(adslImportVO, doorAdsl);
                doorAdsl.setHouseId(doorHouse.getId());

                String standardAddress = StrUtil.trimToEmpty(adslImportVO.getStandardAddress());
                String adslKey = doorHouse.getId() + "-" + standardAddress;
                DoorAdsl existDoorAdsl = adslKeyMap.get(adslKey);

                if (existDoorAdsl != null) {
                    doorAdsl.setId(existDoorAdsl.getId());
                    updateCount++;
                    updateList.add(doorAdsl);
                } else {
                    insertCount++;
                    insertList.add(doorAdsl);
                }

            } catch (Exception e) {
                failCount++;
                
                // 记录失败的数据
                DoorAdslImportRespVO failureVO = new DoorAdslImportRespVO();
                // 复制原始数据
                BeanUtil.copyProperties(adslImportVO, failureVO);
                failureVO.setErrorMessage(e.getMessage());
                failureList.add(failureVO);
            }
        }
        if (!insertList.isEmpty()) {
            easyEntityQuery.insertable(insertList).batch().executeRows(true);
        }

        // 批量更新房产
        if (!updateList.isEmpty()) {
            easyEntityQuery.updatable(updateList).batch().executeRows();
        }
        
        Map<String, Object> result = new HashMap<>();
        result.put("message", StrUtil.format("完成!新增{},修改{},失败{}!", insertCount, updateCount, failCount));
        result.put("insertCount", insertCount);
        result.put("updateCount", updateCount);
        result.put("failCount", failCount);
        result.put("failureList", failureList);
        
        return result;
    }

    public void changeGuid(DoorAdslChangeGuidReqVO reqVO) {
        DoorAdsl doorAdsl = easyEntityQuery.queryable(DoorAdsl.class).where(x -> x.id().eq(reqVO.getId())).firstOrNull();
        if (doorAdsl != null) {
            doorAdsl.setJguid(doorAdsl.getXguid());
            doorAdsl.setXguid(reqVO.getXguid());

            DoorGuidLog doorGuidLog = new DoorGuidLog();
            doorGuidLog.setAdslId(doorAdsl.getId());
            doorGuidLog.setJguid(doorAdsl.getJguid());
            doorGuidLog.setXguid(doorAdsl.getXguid());
            doorGuidLog.setCreateTime(DateUtils.getNowDate());
            doorGuidLog.setReason(reqVO.getReason());
            easyEntityQuery.insertable(doorGuidLog).executeRows();


            easyEntityQuery.updatable(doorAdsl).executeRows();
        }
    }
}
